home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XS.ZIP / MAIL / MAILLIB.C < prev    next >
C/C++ Source or Header  |  1992-11-27  |  20KB  |  578 lines

  1. /*--------------------------------------------------------------------*/
  2. /*    m a i l l i b . c                                               */
  3. /*                                                                    */
  4. /*    Mail user agent subroutine library for UUPC/extended            */
  5. /*                                                                    */
  6. /*    Changes Copyright (c) 1990-1992 by Kendra Electronic            */
  7. /*    Wonderworks; all rights reserved except those explicitly        */
  8. /*    granted by the UUPC/extended license.                           */
  9. /*--------------------------------------------------------------------*/
  10.  
  11. /*--------------------------------------------------------------------*/
  12. /*    Change History:                                                 */
  13. /*                                                                    */
  14. /*       3 May 90 Create from mail.c                                  */
  15. /*       16 Jun 90:  Added support for mail (~) subcommands      pdm  */
  16. /*                   chgd calling seq of Collect_Mail to support      */
  17. /*                         above                                      */
  18. /*                   chges to CopyMsg to support ~i subcmd            */
  19. /*                   mods to SendMail to support autosign option      */
  20. /*                   broke out signature append code to seperate fn   */
  21. /*                   added support for alternate signature file       */
  22. /*--------------------------------------------------------------------*/
  23.  
  24. /*
  25.  *    $Id: MAILLIB.C 1.2 1992/11/27 14:36:10 ahd Exp $
  26.  *
  27.  *    $Log: MAILLIB.C $
  28.  * Revision 1.2  1992/11/27  14:36:10  ahd
  29.  * Use scrsize() for screen size
  30.  *
  31.  */
  32.  
  33. #include <ctype.h>
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <string.h>
  37.  
  38. #include "lib.h"
  39. #include "address.h"
  40. #include "hlib.h"
  41. #include "mlib.h"
  42. #include "alias.h"
  43. #include "mail.h"
  44. #include "maillib.h"
  45. #include "scrsize.h"
  46.  
  47. #define  INDENT "> "
  48.  
  49. /*--------------------------------------------------------------------*/
  50. /*       Local variables                                              */
  51. /*--------------------------------------------------------------------*/
  52.  
  53. static int PageCount = 0;
  54.  
  55. static char *ignorelist[] =  { "Message-ID:",
  56.                         "Received:",
  57.                         "Status: ",
  58.                         "X-Mailer: ",
  59.                         "From " ,
  60.                         "Path: ",
  61.                         "Lines: ",
  62.                         "References: ",
  63.                         "" };
  64.  
  65. currentfile();                /* Define current file for panic()     */
  66.  
  67. /*--------------------------------------------------------------------*/
  68. /*    P a g e r                                                       */
  69. /*                                                                    */
  70. /*    Page through a message                                          */
  71. /*                                                                    */
  72. /*    There are hooks here to let the user use his/her own pager,     */
  73. /*    like LIST, MORE, or LESS.  We just write the message out to     */
  74. /*    a temporary file and invoke the appropriate external program    */
  75. /*    to do the browsing.                                             */
  76. /*--------------------------------------------------------------------*/
  77.  
  78. boolean Pager(const int msgnum,
  79.               boolean external,
  80.               copyopt received,
  81.               const boolean reset)
  82. {
  83.    long nextloc;
  84.    char *browse   = NULL;
  85.    char buf[BUFSIZ];
  86.    boolean exit  = FALSE;        /* Flag for PRE-MATURE exit   ahd   */
  87.    FILE *fmailbag;
  88.  
  89.    if (msgnum == -1)
  90.       return FALSE;
  91.  
  92.    if (bflag[F_PAGER])           /* User want pager option inverted? */
  93.       external = ! external;     /* Yes --> Do the inversion         */
  94.  
  95.    if (letters[msgnum].status < M_READ)
  96.       letters[msgnum].status = M_READ;
  97.  
  98.    if (external && (E_pager != nil(char)))
  99.    {
  100.       browse = mktempname( NULL,"TMP" );/* Get a temporary file name */
  101.  
  102.       if ((fmailbag = FOPEN(browse, "w", TEXT)) == nil(FILE))
  103.       {
  104.          printerr(browse);
  105.          printmsg(0,"Cannot open browse file %s",browse);
  106.          return FALSE;
  107.       } /* if */
  108.       CopyMsg(msgnum, fmailbag, received, FALSE);
  109.       fclose(fmailbag);
  110.  
  111.       L_invoke_pager(E_pager, browse);
  112.       remove(browse);
  113.       free(browse);
  114.  
  115.    } /* if */
  116.    else {
  117.       fseek(fmailbox, letters[msgnum].adr , SEEK_SET);
  118.       nextloc = letters[msgnum + 1].adr;
  119.  
  120.       if ( reset )
  121.          ClearScreen();
  122.       else
  123.          PageLine("\n");
  124.  
  125.       sprintf(buf,"Mailbox item %d:\n",msgnum + 1);
  126.       PageLine(buf);
  127.       while (ftell(fmailbox) < nextloc && (!exit) &&
  128.          fgets(buf, BUFSIZ, fmailbox) != nil(char))
  129.       {
  130.          boolean print = TRUE;
  131.  
  132.          switch(received)
  133.          {
  134.             case nocontinue:
  135.                if ((*buf != '\n') && !isgraph(*buf)) {
  136.                   print = FALSE;
  137.                   break;
  138.                }
  139.                else
  140.                   received = noreceived;
  141.             case noreceived:
  142.             {
  143.                char entry = 0;
  144.                while ( strlen(ignorelist[entry]) && print )
  145.                {
  146.                   if (equalni(ignorelist[entry],
  147.                         buf,strlen(ignorelist[entry])))
  148.                   {
  149.                      print = FALSE;
  150.                      received = nocontinue;
  151.                   }
  152.                   else
  153.                      entry++;
  154.                } /* while */
  155.             } /* case noreceived */
  156.          } /* switch */
  157.          if (received != seperators)
  158.             if (equal(buf,"\n"))
  159.                received = seperators;
  160.  
  161.          if (print)
  162.             if (PageLine(buf))         /* Exit if the user hits Q    */
  163.                exit = TRUE;
  164.       } /* while */
  165.  
  166.       if (equal(buf,"\n") && (!exit))                 /* ahd   */
  167.          putchar('\n');                               /* ahd   */
  168.    } /* else */
  169.  
  170.    return ! exit;
  171. } /*Pager*/
  172.  
  173.  
  174. /*--------------------------------------------------------------------*/
  175. /*    S u b _ P a g e r                                               */
  176. /*       pager for the ~p mail subcommand                             */
  177. /*       page through a mail message currently being entered          */
  178. /*                                                                    */
  179. /*    Clone of the Pager function                                     */
  180. /*--------------------------------------------------------------------*/
  181.  
  182. void Sub_Pager(const char *tinput,
  183.                      boolean external )
  184. {
  185.    boolean exit  = FALSE;        /* Flag for PRE-MATURE exit   ahd   */
  186.  
  187.    if (bflag[ F_PAGER ])
  188.       external = ! external;
  189.  
  190.    if ( external && (E_pager != nil(char)) )
  191.       L_invoke_pager(E_pager, tinput);
  192.    else {
  193.       FILE *finput;
  194.       char buf[BUFSIZ];
  195.       finput = FOPEN(tinput, "r", TEXT);
  196.       if (finput == NULL) {
  197.          printmsg(0,"Cannot open file %s for display",tinput);
  198.          printerr(tinput);
  199.          return;
  200.       }
  201.       PageReset();
  202.       ClearScreen();
  203.       while ( (!exit) && fgets(buf, BUFSIZ, finput) != nil(char))
  204.       {
  205.         if (PageLine(buf))         /* Exit if the user hits Q  */
  206.            exit = TRUE;
  207.       }
  208.       fclose(finput);
  209.    }
  210.  
  211. } /*Sub_Pager*/
  212.  
  213. /*--------------------------------------------------------------------*/
  214. /*    P a g e R e s e t                                               */
  215. /*                                                                    */
  216. /*    Reset page function to top of page                              */
  217. /*--------------------------------------------------------------------*/
  218.  
  219. void PageReset()
  220. {
  221.    PageCount = 0;
  222. } /*PageReset*/
  223.  
  224. /*--------------------------------------------------------------------*/
  225. /*    P a g e L i n e                                                 */
  226. /*                                                                    */
  227. /*    Print one line when paging through a file                       */
  228. /*--------------------------------------------------------------------*/
  229.  
  230. boolean PageLine(char *line)
  231. {
  232.  
  233.    short pagesize = scrsize() - 3;
  234.    fputs(line, stdout);
  235.  
  236.    PageCount = PageCount + 1 + strlen(line) / 81; /* Handle long lines  */
  237.  
  238.    if (PageCount > (pagesize))
  239.    {
  240.       int c;
  241.       fputs("More?", stdout);
  242.       c = Get_One();
  243.  
  244.       switch (tolower(c))
  245.       {
  246.          case 'q':
  247.          case '\003':
  248.          case 'n':                        /* Because that's what I
  249.                                              keep Pressing           */
  250.          case 'x':
  251.             fputs("\rAborted.\n", stdout);
  252.             return TRUE;
  253.  
  254.          case 'd':
  255.             PageCount = pagesize / 2;     /* Half a Page More */
  256.             break;
  257.  
  258.          case '\r':
  259.             PageCount = pagesize;         /* Only print one line  */
  260.             break;
  261.  
  262.          default:
  263.             PageCount = 0;                /* Print full screen    */
  264.       }
  265.       fputs("\r      \r",stdout);
  266.    }
  267.  
  268.    return FALSE;
  269.  
  270. } /*PageLine*/
  271.  
  272. /*--------------------------------------------------------------------*/
  273. /*    C o p y M s g                                                   */
  274. /*                                                                    */
  275. /*    Copy a message                                                  */
  276. /*                                                                    */
  277. /*    Allows copying message with one or more of the options          */
  278. /*    specified in the copyopt data type.                             */
  279. /*--------------------------------------------------------------------*/
  280.  
  281. boolean CopyMsg(int msgnum, FILE *f, copyopt headers, boolean indent)
  282. {
  283.    long nextloc;
  284.    boolean print;
  285.    char buf[BUFSIZ];
  286.  
  287. /*--------------------------------------------------------------------*/
  288. /*                 Write a separator line, if needed                  */
  289. /*--------------------------------------------------------------------*/
  290.  
  291.    if (headers == seperators)
  292.    {
  293.       if (fputs(MESSAGESEP,f) == EOF)     /* Write out separator line   */
  294.       {
  295.          printerr("CopyMsg");
  296.          panic();
  297.       } /* if (fputs(MESSAGESEP,f) == EOF) */
  298.    } /* if (headers == seperators) */
  299.  
  300. /*--------------------------------------------------------------------*/
  301. /*             else add a one line from line, if desired              */
  302. /*--------------------------------------------------------------------*/
  303.  
  304.    else if (headers == fromheader )
  305.    {
  306.       register char *sp = buf;
  307.       headers = noheader;                 /* Do not print full header       */
  308.       if (RetrieveLine(letters[msgnum].date, buf, LSIZE))
  309.       {
  310.          register char  *sp = buf;
  311.          while (!isspace(*sp))
  312.             sp++;
  313.          while (isspace(*sp))
  314.             sp++;
  315.          fprintf(f,"On %s,", sp );
  316.       } /* if */
  317.  
  318.       if (RetrieveLine(letters[msgnum].from, buf, BUFSIZ))
  319.       {
  320.          while (!isspace(*sp) && (*sp != '\0'))
  321.             sp++;
  322.          BuildAddress( buf, sp );
  323.       } /* if */
  324.       else
  325.          strcpy(buf,"you");   /* Wimp out without admitting it       */
  326.  
  327.       fprintf(f, " %s wrote:\n", buf) ;
  328.    } /* if (headers == fromheader ) */
  329.  
  330. /*--------------------------------------------------------------------*/
  331. /*              Now position to the front of the letter               */
  332. /*--------------------------------------------------------------------*/
  333.  
  334.    fseek(fmailbox, letters[msgnum].adr , SEEK_SET);
  335.    nextloc = letters[msgnum + 1].adr;
  336.  
  337.    while (ftell(fmailbox) < nextloc &&
  338.       fgets(buf, BUFSIZ, fmailbox) != nil(char)) {
  339.  
  340. /*--------------------------------------------------------------------*/
  341. /*               Determine if we should write the line                */
  342. /*--------------------------------------------------------------------*/
  343.  
  344.       print = TRUE;
  345.  
  346.       switch (headers)
  347.       {
  348.          case noheader:
  349.             print = FALSE;
  350.             break;
  351.  
  352.          case nocontinue:
  353.             if ((*buf != '\n') && !isgraph(*buf)) {
  354.                print = FALSE;
  355.                break;
  356.             }
  357.             else
  358.                headers = noreceived;
  359.                /* Fall through ... */
  360.          case noreceived:
  361.          {
  362.             char entry = 0;
  363.             while ( strlen(ignorelist[entry]) && print )
  364.             {
  365.                if (equalni(ignorelist[entry],buf,strlen(ignorelist[entry])))
  366.                {
  367.                   print = FALSE;
  368.                   headers = nocontinue;
  369.                }
  370.                else
  371.                   entry++;
  372.             }
  373.          } /* case noreceived */
  374.                /* Fall through */
  375.          case noseperator:
  376.          case seperators:
  377.             break;
  378.  
  379.          default:
  380.             printmsg(0,"CopyMsg: Bad header copy state of %d",headers);
  381.             panic();
  382.       } /* switch */
  383.  
  384. /*--------------------------------------------------------------------*/
  385. /*                 If we should print the line, do so                 */
  386. /*--------------------------------------------------------------------*/
  387.  
  388.       if (print)
  389.       {
  390.          if (indent)
  391.          {
  392.             if ( fputs(INDENT , f ) == EOF )
  393.             {
  394.                printerr( "CopyMsg" );
  395.                panic();
  396.             } /* if ( fputs(INDENT , f ) == EOF ) */
  397.          } /* if (indent) */
  398.  
  399.          if ( fputs(buf , f ) == EOF )
  400.          {
  401.             printerr( "CopyMsg" );
  402.             panic();
  403.          } /* if ( fputs(buf , f ) == EOF ) */
  404.  
  405.       } /* if (print) */
  406.  
  407. /*--------------------------------------------------------------------*/
  408. /*  If end of the header, print all data until the end of the input   */
  409. /*--------------------------------------------------------------------*/
  410.  
  411.       if ( (headers != seperators) && equal(buf, "\n") )
  412.          headers = seperators;
  413.  
  414.    } /*while*/
  415.  
  416.    return TRUE;
  417. } /*CopyMsg*/
  418.  
  419. /*--------------------------------------------------------------------*/
  420. /*    N u m e r i c                                                   */
  421. /*                                                                    */
  422. /*    Determine if a string is numeric.  Returns TRUE if string is    */
  423. /*    numeric, else FALSE.                                            */
  424. /*--------------------------------------------------------------------*/
  425.  
  426.  boolean Numeric( const char *number)
  427.  {
  428.    char *column = (char *) number;
  429.  
  430.    if (*column == '\0')
  431.       return FALSE;
  432.  
  433.    while( isdigit(*column) )  /* Scan to string end or 1st non-digit */
  434.       column++;
  435.  
  436.    return *column == '\0';    /* Success if whole string was made of
  437.                                  digits                              */
  438.  } /* Numeric */
  439.  
  440. /*--------------------------------------------------------------------*/
  441. /*    R e t r i e v e L i n e                                         */
  442. /*                                                                    */
  443. /*    Read a line from a mail header, if available                    */
  444. /*--------------------------------------------------------------------*/
  445.  
  446. boolean RetrieveLine(long adr, char *line, const size_t len)
  447. {
  448.    char *cp = line;
  449.    size_t count;
  450.  
  451.    *line = '\0';              /* Insure nothing to find              */
  452.    if (adr == MISSING)        /* No information to read?             */
  453.       return FALSE;           /* Report this to caller               */
  454.  
  455.    if (fseek(fmailbox, adr, SEEK_SET)) /* Position to data           */
  456.    {                          /* Have a problem?                     */
  457.       printerr("mailbox");    /* Yes --> Report and return           */
  458.       return FALSE;
  459.    }
  460.  
  461. /*--------------------------------------------------------------------*/
  462. /*                     Actually read the data in                      */
  463. /*--------------------------------------------------------------------*/
  464.  
  465.    count = fread(line, sizeof *line, len-1, fmailbox);
  466.  
  467.    if ((count < (len-1)) && ferror( fmailbox ))
  468.    {
  469.       printerr( "RetrieveLine");
  470.       return FALSE;
  471.    }
  472.  
  473.    line[count] = '\0';        /* Terminate the string read           */
  474.  
  475. /*--------------------------------------------------------------------*/
  476. /*    A field continues until a new field begins in column of the     */
  477. /*    next line or the header ends (an empty line); find the end      */
  478. /*    of the field, trimming extra white space from the beginning     */
  479. /*    of each line as we go                                           */
  480. /*--------------------------------------------------------------------*/
  481.  
  482.    while( (cp = strchr(cp , '\n')) != NULL )
  483.    {
  484.       if ((cp[1] == '\n') || !isspace(cp[1]))   /* End of field?     */
  485.          *cp = '\0';          /* Yes --> Terminate string            */
  486.       else {
  487.          char *next;
  488.  
  489.          *cp++ = ' ';         /* Convert line break to whitespace    */
  490.          next = ++cp;         /* Get first position of new line      */
  491.          while( isspace( *next ) )  /* Ignore leading white space    */
  492.             next++;
  493.  
  494.          memmove( cp , next , strlen(next) + 1 );
  495.                               /* Trim leading white space            */
  496.       } /* else */
  497.    } /* while */
  498.  
  499.    return TRUE;
  500.  
  501. } /*RetrieveLine*/
  502.  
  503. /*--------------------------------------------------------------------*/
  504. /*    R e t u r n A d d r e s s                                       */
  505. /*                                                                    */
  506. /*    Returns the user name (if available and requested) or           */
  507. /*    E-mail address of the user                                      */
  508. /*                                                                    */
  509. /*    Written by ahd 15 July 1989                                     */
  510. /*--------------------------------------------------------------------*/
  511.  
  512. void ReturnAddress(char *line, struct ldesc *ld)
  513. {
  514.    char buffer[BUFSIZ];
  515.  
  516.    if (!RetrieveLine(ld->from, buffer, BUFSIZ))
  517.                                           /* From: line available?   */
  518.       strcpy(line,"-- Unknown --");       /* No --> Return error     */
  519.    else {
  520.       char *begin = buffer;
  521.       while (!isspace(*begin) && (*begin != '\0'))
  522.          begin++;
  523.       if (strlen(begin))
  524.          ExtractName(line,begin);         /* Yes --> Return name     */
  525.       else
  526.          strcpy(line,"-- Invalid From: line --");
  527.    }
  528.  
  529.    return;
  530.  
  531. } /*ReturnAddress*/
  532.  
  533. /*--------------------------------------------------------------------*/
  534. /*    s a y o p t i o n s                                             */
  535. /*                                                                    */
  536. /*    Announce user options in effect                                 */
  537. /*--------------------------------------------------------------------*/
  538.  
  539. void sayoptions( FLAGTABLE *flags)
  540. {
  541.  
  542.    size_t subscript;
  543.    size_t used = 0;
  544.  
  545.    printf("\nThe following options are set:\n");
  546.  
  547.    for (subscript = 0; (subscript < F_LAST); subscript++)
  548.    {
  549.          size_t width;
  550.  
  551.          if (flags[subscript].bits & B_GLOBAL)
  552.             continue;               /* Don't print system options */
  553.  
  554.          width = 1 + strlen( flags[subscript].sym ) +
  555.                  ( bflag[ flags[subscript].position ] ? 0 : 2 );
  556.  
  557.          used += width;
  558.          if ( subscript > 0 )
  559.          {
  560.             if ( used > 79 )
  561.             {
  562.                putchar('\n');
  563.                used = width;
  564.             } /* if ( used > 79 ) */
  565.             else
  566.                putchar(' ');
  567.          } /* if ( subscript > 0 ) */
  568.  
  569.          printf("%s%s",
  570.             bflag[ flags[subscript].position ] ? "" : "no" ,
  571.             flags[subscript].sym );
  572.  
  573.    } /* for */
  574.  
  575.    putchar('\n');
  576.  
  577. } /* sayoptions */
  578.